using System;
using System.Reflection;
using System.IO;
using FibMatrix;
using FibMatrix.IO;
using UnityEditor;
using UnityEditor.Callbacks;
#if UNITY_IOS
using UnityEditor.iOS.Xcode;
#endif
using UnityEngine;

[InitializeOnLoad]
public partial class AutoBuilder
{
	[MenuItem("Tools/Export Android Project", false)]
    public static void BuildAndroid()
	{
		Debug.Log ("Perform Android Build");
		CommonPreBuild();
		
		string androidSDKRoot = EditorPrefs.GetString("AndroidSdkRoot");
		if (!Directory.Exists(androidSDKRoot))
        {
	        androidSDKRoot = System.Environment.GetEnvironmentVariable("ANDROID_SDK_HOME");
	        EditorPrefs.SetString("AndroidSdkRoot", androidSDKRoot);
        }
        Debug.Log(androidSDKRoot);

        string androidNdkRoot = EditorPrefs.GetString("AndroidNdkRoot");
        if (!Directory.Exists(androidNdkRoot))
        {
	        androidNdkRoot = System.Environment.GetEnvironmentVariable("ANDROID_NDK_HOME");
	        EditorPrefs.SetString("AndroidNdkRoot", androidNdkRoot);
        }
        Debug.Log(androidNdkRoot);
        
        string extDefine = "";
        var additionMacro = Environment.GetEnvironmentVariable("ADDITION_MACRO");
        if (!string.IsNullOrEmpty(additionMacro))
        {
	        additionMacro = additionMacro.Replace(" ", "");
	        if (!additionMacro.StartsWith(";"))
	        {
		        extDefine = ";" + additionMacro;
	        }
        }
        
        string buildSymbols = 
	        PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android) + extDefine;
        PlayerSettings.SetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android, buildSymbols);
        
        Debug.Log($"BuildAndroid buildSymbols: {PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android)}");
        
		AssetDatabase.Refresh();
		EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);
		EditorUserBuildSettings.development = Environment.GetEnvironmentVariable("IS_DEBUG") == "true";;
		PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.Android, EditorUserBuildSettings.development ? Il2CppCompilerConfiguration.Debug : Il2CppCompilerConfiguration.Release);
		EditorUserBuildSettings.androidBuildType =
			EditorUserBuildSettings.development ? AndroidBuildType.Debug : AndroidBuildType.Release;
		PlayerSettings.SplashScreen.show = false;

		string distributePlatform = System.Environment.GetEnvironmentVariable("DISTRIBUTE_PLATFORM");
		if (string.IsNullOrEmpty(distributePlatform))
		{
			distributePlatform = "android";
		}
		
		string productName = System.Environment.GetEnvironmentVariable("PRODUCT_NAME");
		if (!string.IsNullOrEmpty(productName))
		{
			PlayerSettings.productName = productName;
		}
		string versionNumberRaw = System.Environment.GetEnvironmentVariable("VERSIONCODE");
		Debug.Log(versionNumberRaw);

		int versionNumber;
		int.TryParse(versionNumberRaw, out versionNumber);
		PlayerSettings.Android.bundleVersionCode = versionNumber;

		string versionString = System.Environment.GetEnvironmentVariable("GAME_VERSION");

		PlayerSettings.bundleVersion = versionString;
		PlayerSettings.Android.splashScreenScale = AndroidSplashScreenScale.ScaleToFill;
		PlayerSettings.Android.preferredInstallLocation = AndroidPreferredInstallLocation.ForceInternal;
		PlayerSettings.SetManagedStrippingLevel(BuildTargetGroup.Android, ManagedStrippingLevel.Low);
		EditorUserBuildSettings.exportAsGoogleAndroidProject = true;

		
		// string loadingAniPlatformDir = "Android";
		// string absLoadingAnimationDir = FibMatrix.IO.PackageManager.streamingAssetsPath + "/LoadingAnimation";
		//
		// string[] platformDirs = Directory.GetDirectories(absLoadingAnimationDir);
		// foreach(var platformPath in platformDirs)
		// {
		// 	if (Path.GetFileName(platformPath) != loadingAniPlatformDir)
		// 	{
		// 		CommonUtil.DeleteDir(platformPath);
		// 	}
		// }
//
		// string appIconPrefix = "Assets/Textures/UI/AppIcon/";
		// appIconDirectory = appIconPrefix + appIconDirectory;
		// string[] iconFiles = Directory.GetFiles(appIconDirectory, "*.png");
		// foreach	(string iconfile in iconFiles)
		// {
		// 	File.Copy(iconfile, appIconPrefix + Path.GetFileName(iconfile), true);
		// }
	 //
//          AssetDatabase.Refresh();
		// CommonUtil.CheckDirectory("Build/Temp/exportFilePath.tmp");
		// string apkUnsignedName = string.Format("cod_{0}_{1}_unsigned.apk", channel, buildId + apkNameSuffix);
		// string apkSignedName = string.Format("cod_{0}_{1}_signed.apk", channel, buildId + apkNameSuffix);
		// string resignTemplate = File.ReadAllText("Assets/Build/if_resign.template");
		// resignTemplate = resignTemplate.Replace("${unsignedName}", apkUnsignedName);
		// resignTemplate = resignTemplate.Replace("${signedName}", apkSignedName);
		// resignTemplate = resignTemplate.Replace("${finalName}", apkFinalName);
		// resignTemplate = resignTemplate.Replace("${keystoreName}", "../../" + PlayerSettings.Android.keystoreName);
		// resignTemplate = resignTemplate.Replace("${keyAliasName}", PlayerSettings.Android.keyaliasName);
		// resignTemplate = resignTemplate.Replace("${keyPass}", PlayerSettings.Android.keyaliasPass);
		// resignTemplate = resignTemplate.Replace("${keystorePass}", PlayerSettings.Android.keystorePass);
		//
		// File.WriteAllText("Build/Temp/resign.sh", resignTemplate);
		//
		// string unsignedApkPath = string.Format("Build/Temp/{0}", apkUnsignedName);
		// File.WriteAllText("Build/Temp/exportFilePath.tmp", unsignedApkPath);
		string projectPath = Path.Combine("NativeProj", "Android", "UnityOutput");
		if (Directory.Exists(projectPath))
		{
			Directory.Delete(projectPath, true);
		}

		var options = BuildOptions.SymlinkLibraries;
		if (EditorUserBuildSettings.development)
		{
			options |= BuildOptions.Development;
		}
		BuildPipeline.BuildPlayer(GetScenePaths(), projectPath,
			BuildTarget.Android, options);
		if (Application.isBatchMode)
		{
			string buildLockFile = Environment.GetEnvironmentVariable("BUILD_LOCK_PATH");
			if (!string.IsNullOrEmpty(buildLockFile) && File.Exists(buildLockFile))
			{
				File.Delete(buildLockFile);
			}
		}
	}
    
    [MenuItem("Tools/Export iOS Project", false)]
    public static void BuildIOS()
	{
		Debug.Log ("Perform iOS Build");
		CommonPreBuild();
		
		// string androidSDKRoot = EditorPrefs.GetString("AndroidSdkRoot");
		//
  //       if (!Directory.Exists(androidSDKRoot))
  //       {
	 //        androidSDKRoot = System.Environment.GetEnvironmentVariable("ANDROID_SDK_HOME");
	 //        EditorPrefs.SetString("AndroidSdkRoot", androidSDKRoot);
  //       }
  //       Debug.Log(androidSDKRoot);
  //
  //       string androidNdkRoot = EditorPrefs.GetString("AndroidNdkRoot");
  //       if (!Directory.Exists(androidNdkRoot))
  //       {
	 //        androidNdkRoot = System.Environment.GetEnvironmentVariable("ANDROID_NDK_HOME");
	 //        EditorPrefs.SetString("AndroidNdkRoot", androidNdkRoot);
  //       }
  //       Debug.Log(androidNdkRoot);
        
		AssetDatabase.Refresh();
		EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, BuildTarget.iOS);
		EditorUserBuildSettings.development = Environment.GetEnvironmentVariable("IS_DEBUG") == "true";
		PlayerSettings.SetIl2CppCompilerConfiguration(BuildTargetGroup.iOS, EditorUserBuildSettings.development ? Il2CppCompilerConfiguration.Debug : Il2CppCompilerConfiguration.Release);
		EditorUserBuildSettings.iOSBuildConfigType =
			EditorUserBuildSettings.development ? iOSBuildType.Debug : iOSBuildType.Release;
		// PlayerSettings.iOS.
		PlayerSettings.SplashScreen.show = false;

		string distributePlatform = System.Environment.GetEnvironmentVariable("DISTRIBUTE_PLATFORM");
		if (string.IsNullOrEmpty(distributePlatform))
		{
			distributePlatform = "applestore";
		}
		
		string productName = System.Environment.GetEnvironmentVariable("PRODUCT_NAME");
		if (!string.IsNullOrEmpty(productName))
		{
			PlayerSettings.productName = productName;
		}
		string versionNumberRaw = System.Environment.GetEnvironmentVariable("VERSIONCODE");
		Debug.Log(versionNumberRaw);

		PlayerSettings.iOS.buildNumber = versionNumberRaw;

		string versionString = System.Environment.GetEnvironmentVariable("GAME_VERSION");

		PlayerSettings.bundleVersion = versionString;
		// PlayerSettings.iOS = AndroidSplashScreenScale.ScaleToFill;
		PlayerSettings.SetManagedStrippingLevel(BuildTargetGroup.iOS, ManagedStrippingLevel.Low);
		
		
		string projectPath = Path.Combine("NativeProj", "iOS", "UnityOutput");

		var options = BuildOptions.SymlinkLibraries;
		if (EditorUserBuildSettings.development)
		{
			options |= BuildOptions.Development;
		}

		string replaceMode = System.Environment.GetEnvironmentVariable("REPLACE_MODE");
		if (string.IsNullOrEmpty(replaceMode) && Directory.Exists(projectPath))
		{
			options |= BuildOptions.AcceptExternalModificationsToPlayer;
		}

		bool retry = false;
		try
		{
			BuildPipeline.BuildPlayer(GetScenePaths(), projectPath,
				BuildTarget.iOS, options);
		}
		catch (InvalidOperationException e)
		{
			if (e.ToString().Contains("The build cannot be appended"))
			{
				retry = true;
				options &= ~BuildOptions.AcceptExternalModificationsToPlayer;
			}
			else
			{
				throw;	
			}
		}

		if (retry)
		{
			BuildPipeline.BuildPlayer(GetScenePaths(), projectPath,
				BuildTarget.iOS, options);
		}

		if (Application.isBatchMode)
		{
			string buildLockFile = Environment.GetEnvironmentVariable("BUILD_LOCK_PATH");
			if (!string.IsNullOrEmpty(buildLockFile) && File.Exists(buildLockFile))
			{
				File.Delete(buildLockFile);
			}
		}
	}
    private static string[] GetScenePaths()
    {
	    string[] scenes = new string[EditorBuildSettings.scenes.Length];

	    for (int i = 0; i < scenes.Length; i++)
	    {
		    if (EditorBuildSettings.scenes[i].enabled)
		    {
			    scenes[i] = EditorBuildSettings.scenes[i].path;
		    }
	    }

	    return scenes;
    }

	[PostProcessBuild(99)]
	public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject)
	{
		if (target == BuildTarget.Android)
		{
			Debug.Log("AutoBuilder Post Build");
			string srcDir = Path.Combine("Temp", "StagingArea", "symbols");
			string dstDir = Path.Combine("Build", "Symbols");
			if (Directory.Exists(srcDir) && Directory.Exists(dstDir))
			{
				CopyTargetABI(srcDir, dstDir, "arm64-v8a");
				CopyTargetABI(srcDir, dstDir, "armeabi-v7a");
			}
		}
		else if (target == BuildTarget.WebGL)
		{
			// webgl工程刚生成好，还没创建小游戏工程
		}
		else if (target == BuildTarget.iOS)
		{
#if UNITY_IOS			
			string infoPlistPath = pathToBuiltProject + "/Info.plist";
			var plist = new PlistDocument();
			plist.ReadFromFile(infoPlistPath);
			plist.root.SetBoolean("ITSAppUsesNonExemptEncryption", false);
			plist.WriteToFile(infoPlistPath);
#endif			
		}
	}
	
	/// <summary>
	/// 构建前修改、处理资源
	/// </summary>
	static void CommonPreBuild()
	{
		Debug.Log ("PreProcessAssets");
		// 底包不引用字体，降低底包大小，去掉字体的内存冗余
		Type type = typeof(TMPro.TMP_Settings);
		FieldInfo fieldInfo = type.GetField("m_defaultFontAsset", BindingFlags.NonPublic | BindingFlags.Instance);
		fieldInfo.SetValue(TMPro.TMP_Settings.instance, null);
		// 不用save，内存对象变了构建就不会包含那个字体
	}
		

	public static void CopyDirectory(string sourceDir, string destDir)
	{
		// 如果目标目录不存在，则创建它
		if (!Directory.Exists(destDir))
		{
			Directory.CreateDirectory(destDir);
		}

		// 复制所有文件到目标目录
		foreach (string file in Directory.GetFiles(sourceDir))
		{
			string destFile = Path.Combine(destDir, Path.GetFileName(file));
			File.Copy(file, destFile, true);
		}

		// 递归复制所有子目录
		foreach (string subdir in Directory.GetDirectories(sourceDir))
		{
			string destSubdir = Path.Combine(destDir, Path.GetFileName(subdir));
			CopyDirectory(subdir, destSubdir);
		}
	}
	private static void CopyTargetABI(string srcDir, string dstDir, string abi)
	{
		string[] unstripFiles = Directory.GetFiles(Path.Combine(srcDir, abi), "*.so");
		Debug.Log("so file count " + unstripFiles.Length);
		foreach (var unstripFile in unstripFiles)
		{
			string fileName = Path.GetFileName(unstripFile);
			if (fileName.Contains(".dbg.so"))
			{
				continue;
			}
			Debug.Log("Copy " + fileName);
			File.Copy(unstripFile, Path.Combine(dstDir, abi, fileName.Replace(".sym", "")), true);
		}
	}
}